/***
 *  HighCharts extends api
 */
(function (H) {

    Highcharts.setOptions({
        global: {
            useUTC: true,
            /**
             * Use moment-timezone.js to return the timezone offset for individual
             * timestamps, used in the X axis labels and the tooltip header.
             */
            getTimezoneOffset: function (timestamp) {
                var offset = moment(timestamp).utcOffset();
                return -offset;
            }
        }
    });

    H.Chart.prototype.getAllSeries = function () {
        var allSeries = [];
        for (var index = 0; index < this.series.length; index++) {
            var series = this.series[index];
            if (series.name != "Navigator") {
                allSeries.push(series);
            }
        }
        return allSeries;
    };

    H.Chart.prototype.getAllYAxes = function () {
        var axes = [];
        for (index = 0; index < this.yAxis.length; index++) {
            var axis = this.yAxis[index];
            if (axis.options.id != "navigator-y-axis") axes.push(axis);
        }

        return axes;
    }

    H.Chart.prototype.getAllXAxes = function () {
        var axes = [];
        for (index = 0; index < this.xAxis.length; index++) {
            var axis = this.yAxis[index];
            if (axis.options.id != "navigator-x-axis") axes.push(axis);
        }

        return axes;
    }

    H.Chart.prototype.resetYAxisExtremes = function (inRedraw) {
        var axes = this.getAllYAxes();
        var index;
        var redraw = isDefined(inRedraw) ? inRedraw : true;
        for (index = 0; index < axes.length; index++) {
            this.setAxisExtremes(axes[index], null, null, redraw);


        }
    }

    H.Chart.prototype.getRenderedSeries = function () {
        var allSeries = [];
        var filtered = this.getAllSeries();
        for (var index = 0; index < filtered.length; index++) {
            var series = filtered[index];
            if (series.visible == true && series.linkedParent == null && series.name != "Navigator") {
                allSeries.push(series);
            }
        }
        return allSeries;
    }

    H.Chart.prototype.clearAllSeries = function () {

        this.legend.resetTitle();
        while (this.series.length > 0) {
            this.series[0].remove(false);
        }
        this.xAxis[0].setExtremes(null, null, true);

        this.yAxis.forEach(function (yAxis) {
            yAxis.setExtremes(null, null, true);
        });
        this.colorCounter = 0;
        this.symbolCounter = 0;

        this.zoomedTimes = [];
        this.redraw();
    }

    H.Chart.prototype.getSeriesByName = function (seriesName) {
        if (isValued(this.series) == false || this.series.length == 0) {
            return null;
        }
        for (var index = 0; index < this.series.length; index++) {
            var currentSeries = this.series[index];
            if (currentSeries.name == seriesName) {
                return currentSeries;
            }
        }
        return null;
    }

    H.Chart.prototype.removeUnusedYAxis = function () {
        var removedAxis = [];
        this.yAxis.forEach(function (axis) {
            //dont delete the default axis
            if (axis.options.id == "yDefaultAxis") return;
            if (axis.series == null || axis.series.length == 0) {
                removedAxis.push(axis);
            }
        });

        removedAxis.forEach(function (axis) {
            axis.remove(true);
        });
    }

    H.Chart.prototype.STEP_MODES = {
        "NONE": 0,
        "LEFT": 1,
        "CENTER": 2,
        "RIGHT": 3
    };

    H.Chart.prototype.getAxisColorOptions = function (axisColor) {
        if(isNotValued(axisColor)){
            axisColor = defaultAxisColor;
        }
        return {
            lineColor: axisColor,
            tickColor: axisColor,
            labels: {
                style: {
                    color: axisColor
                }
            }
        };
    }

    var defaultAxisColor = '#ccd6eb';
    H.Chart.prototype.colorYAxis = function () {
        if(this.yAxis.length==1){
            this.yAxis[0].update(this.getAxisColorOptions(defaultAxisColor), true);
        }else{
            this.yAxis.forEach(function (axis) {
                
                var axisColor = null;
                axis.series.forEach(function (axisSeries) {
                    if (axisSeries.isDerivedSeries()) {
                        return;
                    }
                    if (axisColor == null) {
                        axisColor = axisSeries.color;
                    }
                    if (axisColor != axisSeries.color) {
                        axisColor = defaultAxisColor;
                    }
                });
                if (axisColor == null) {
                    axisColor = defaultAxisColor;
                }
                axis.update(this.getAxisColorOptions(axisColor), true);
            }.bind(this));
        }
    }

    H.Chart.prototype.getPercentile = function () {
        return this.percentile;
    }

    H.Chart.prototype.getOptionParameter = function (key) {
        if (!this.options || !this.options.mergedOptions) return null;
        var mergedOptions = this.options.mergedOptions;
        var returnValue = mergedOptions[key];
        var type = typeof returnValue;
        if (type == "string" || type == "number" || type == "boolean") {
            if (returnValue != null && type == "string") {
                returnValue = returnValue.toLowerCase().trim();
            }

            return returnValue;
        }
        return null;
    }

    /**
     * Set a parameter programmatically, can be override from excel
     * @param key
     * @param value
     * @returns {null}
     */
    H.Chart.prototype.setOptionParameter = function (key, value) {
        if (!this.options || !this.options.mergedOptions) return null;
        var mergedOptions = this.options.mergedOptions;
        if (isDefined(mergedOptions)) {
            mergedOptions[key] = value;
        }
    }

    H.Chart.prototype.setSeriesStep = function (seriesName, stepMode) {
        var chart = this;
        var series = chart.getSeriesByName(seriesName);
        if (series == null) {
            return;
        }
        var currentStepMode = series.options.step;
        var requestedStepMode = null;
        switch (stepMode) {
            case chart.STEP_MODES.NONE:
                requestedStepMode = null;
                break;
            case chart.STEP_MODES.LEFT:
                requestedStepMode = "left";
                break;
            case chart.STEP_MODES.CENTER:
                requestedStepMode = "center";
                break;
            case chart.STEP_MODES.RIGHT:
                requestedStepMode = "right";
                break;
            default:
                console.log("Unsupported step Mode:", stepMode)
                return;
        }
        if (currentStepMode == requestedStepMode) {
            return;
        }
        series.update({
            step: requestedStepMode
        }, true);

    }

    H.Chart.prototype.isManuallyZoomed = function () {
        if (isNotValued(this.options.manuallyZoomed)) {
            return false;
        }

        return this.options.manuallyZoomed;
    }


    H.Chart.prototype.getCurrentFontSize = function () {
        var size = window.getComputedStyle(document.body, null).fontSize;
        return Number(size.replace("px", ""));
    }

    H.Chart.prototype.changeFontSize = function (absolute) {
        var currentSize = this.getCurrentFontSize();
        if (isNaN(currentSize)) {
            console.error("Can't use font size function, the containing element of the chart does not have a size attached to it or is not in pixels")
            return;
        }
        console.info("Changing font size to: ", absolute);

        document.body.style.fontSize = (absolute) + "px";

        this.setOptionParameter(KEY_CHART_FONT_SIZE, absolute);

    }

    H.Chart.prototype.getSeriesOptionParameter = function(seriesOptions,parameterName ) {
        var chart = this;
        var seriesIndex = chart.series.length;
        var optionPrefix = "series[" +seriesIndex +"].";  
        var option = chart.getOptionParameter( optionPrefix + parameterName );
        if ( option ) {
          return option;
        }
        optionPrefix = "series[\"" +seriesOptions.name +"\"].";  
        option = chart.getOptionParameter( optionPrefix + parameterName );
        if ( option ) {
          return option;
        }
        optionPrefix = "series[" +seriesOptions.name +"].";  
        return chart.getOptionParameter( optionPrefix + parameterName );
    }

    H.Chart.prototype.configSeriesOptions = function( seriesOptions ){
        var lineWidth = this.getSeriesOptionParameter(seriesOptions, "lineWidth" );
        if ( lineWidth ) {
        seriesOptions.lineWidth = lineWidth;
        }
        var dashStyle = this.getSeriesOptionParameter(seriesOptions, "dashStyle" );
        if ( dashStyle ) {
        seriesOptions.dashStyle = dashStyle;
        }
        var step = this.getSeriesOptionParameter(seriesOptions, "step" );
        if ( step ) {
        step = step.toLowerCase();
        if ( step == "none" ) {
            step = null;
        }
        seriesOptions.step = step;
        }
        var color = this.getSeriesOptionParameter(seriesOptions, "color" );
        if ( color ) {
            seriesOptions.color = color;
        }
        return seriesOptions;
    }

    H.Chart.prototype.setAxisExtremes = function (axis, min, max, redraw) {
        //should be an event emitted for yAxis update, this is a circular dependency
        if (this.indicatorCache) {
            this.indicatorCache.clearSeries(axis.series);
        }

        axis.range = null;
        axis.update({
            "min": min,
            "max": max
        }, false);
        axis.setExtremes(min, max, redraw, redraw);
    }



    /**
     * Series extends 
     * 
     */

    H.Series.prototype.getPointsWithinX = function (series, xMin, xMax) {
        var data = [];
        //nulls mean everything
        if (!isDefined(xMin) || !isDefined(xMax) || xMin == null || xMax == null) return series.yData;
        if (!isDefined(series) || series == null || !isDefined(series.xData) || series.xData == null) return data;
        for (var innerIndex = 0; innerIndex < series.xData.length; innerIndex++) {
            var xValue = series.xData[innerIndex];
            var yValue = series.yData[innerIndex];
            if (xValue != null && xValue >= xMin && xValue <= xMax && yValue != null) data.push(yValue);
        }

        return data;
    }

    H.Series.prototype.isDerivedSeries = function () {
        return this.linkedParent != null || this.options.errorMessage;
    }
    H.Series.prototype.getXPoint = function (x) {
        if (!isValued(x) || !isValued(this.points) || this.points.length == 0) return null;
        for (var index = 0; this.points.length; index++) {
            if (this.points[index].x == x) return this.points[index];
        }

        return null;
    };

    Highcharts.Series.prototype.getYAxisIndex = function () {
        if (typeof this.yAxis == "object") {
            return this.yAxis.options.index;
        }
        return 0;
    }

    H.Axis.prototype.getSignificantDigits = function () {
        var significantDigits = AXIS_SIGNIFICANT_DIGITS;
        for ( significantDigits; significantDigits < 10; significantDigits++ ) {
          var previousValue = null;
          for ( var tickIndex = 0; tickIndex < this.tickPositions.length; tickIndex++ ) {
            currentValue = NUMBER_UTILS.formatSignificant( this.tickPositions[ tickIndex ], significantDigits  );
      
            //duplicate...start over with new significant digit
            if ( previousValue != null && currentValue == previousValue ) break;
            previousValue = currentValue;
          }
          //went through whole list with not previous dups...these are sorted
          //there may be a use case where the duplicate is not the previous? can't think of it
          if ( tickIndex == this.tickPositions.length ) break;
        }
      
        return significantDigits;
      }

}(Highcharts))